package config

import (
	"fmt"
	"gitee.com/sansaniot/ssiot-core/config/tool"
	"gitee.com/sansaniot/ssiot-core/config/tool/source"
	"log"
)

var (
	ExtendConfig interface{}
	_cfg         *Settings
)

// Settings 兼容原先的配置结构
type Settings struct {
	Ssiot     Config `yaml:"ssiot"`
	callbacks []func()
}

func (e *Settings) runCallback() {
	for i := range e.callbacks {
		e.callbacks[i]()
	}
}

func (e *Settings) OnChange() {
	e.init()
	log.Println("config change and reload")
}

func (e *Settings) Init() {
	e.init()
	log.Println("config init")
}

func (e *Settings) init() {
	e.Ssiot.Logger.Setup()
	e.Ssiot.multiDatabase()
	e.runCallback()
}

// Config 配置集合
type Config struct {
	Http      *Http                 `yaml:"http"`
	Mqtt      *Mqtt                 `yaml:"mqtt"`
	Ssl       *Ssl                  `yaml:"ssl"`
	Logger    *Logger               `yaml:"logger"`
	Jwt       *Jwt                  `yaml:"jwt"`
	Database  *Database             `yaml:"database"`
	Databases *map[string]*Database `yaml:"databases"`
	Gen       *Gen                  `yaml:"gen"`
	Cache     *Cache                `yaml:"cache"`
	Queue     *Queue                `yaml:"queue"`
	Locker    *Locker               `yaml:"locker"`
	Extend    interface{}           `yaml:"extend"`
	I18n      *I18n                 `yaml:"i18n"`
}

// 多db改造
func (e *Config) multiDatabase() {
	if len(*e.Databases) == 0 {
		*e.Databases = map[string]*Database{
			"*": e.Database,
		}

	}
}

// Setup 载入配置文件
func Setup(s source.Source,
	fs ...func()) {
	_cfg = &Settings{
		Ssiot: Config{
			Http:      HttpConfig,
			Mqtt:      MqttConfig,
			Ssl:       SslConfig,
			Logger:    LoggerConfig,
			Jwt:       JwtConfig,
			Database:  DatabaseConfig,
			Databases: &DatabasesConfig,
			Gen:       GenConfig,
			Cache:     CacheConfig,
			Queue:     QueueConfig,
			Locker:    LockerConfig,
			Extend:    ExtendConfig,
			I18n:      I18nConfig,
		},
		callbacks: fs,
	}
	var err error
	tool.DefaultConfig, err = tool.NewConfig(
		tool.WithSource(s),
		tool.WithEntity(_cfg),
	)
	if err != nil {
		log.Fatal(fmt.Sprintf("New config object fail: %s", err.Error()))
	}
	_cfg.Init()
}
